#include "LuaEngine.h"
#include "LuaFunctor.h"
#include "tools.h"

#define TRACE(...) fprintf(stderr,__VA_ARGS__)

LuaEngine *LuaEngine::instance_ptr  = 0;

LuaEngine::LuaEngine(){
	m_state = luaL_newstate();
	luaL_openlibs(m_state);
}

LuaEngine::~LuaEngine(){
	for(auto i = m_modules.begin();i != m_modules.end();){
		(*i)->UnbindModule(m_state);
		i = m_modules.erase(i);
	}
	m_modules.clear();

	CleanUD(m_state);
	lua_close(m_state);
	m_state = 0;
}

int LuaEngine::runLuaFunction(const char *name,LuaParam *in,int i_count,LuaParam *out,int o_count){
	return CallLuaFunction(m_state,name,in,i_count,out,o_count);
}

int LuaEngine::loadString(const char *str){
	return luaL_loadstring(m_state,str);
}

int LuaEngine::loadData(const char *data,int len,const char *msg){
	return luaL_loadbuffer(m_state,data,len,msg);
}

int LuaEngine::runFile(const char *fname){
	if(!fname){
		TRACE("runFile error:no input file\n");
		return 1;
	}
	int top = lua_gettop(m_state);
	if(luaL_loadfile(m_state,fname)){
		TRACE("loadfile error:%s\n",lua_tostring(m_state,-1));
		lua_settop(m_state,top);
		return 2;
	}
	if(lua_pcall(m_state,0,0,0)){
		TRACE("execute file error:%s\n",lua_tostring(m_state,-1));
		lua_settop(m_state,top);
		return 3;
	}
	return 0;
}

int LuaEngine::bindModule(ILuaBind *bind){
	if(bind){
		auto end = m_modules.end();
		for(auto i = m_modules.begin();i!=end;i++){
			if((*i) == bind){
				return 0;//module bound already
			}
		}
		bind->BindModule(m_state);
		m_modules.push_back(bind);//add module for release use
	}
	return 0;
}